#ifndef FRAKOUTCONTROLLER_H
#define FRAKOUTCONTROLLER_H

#include <QObject>

#include "FrakOutData.h"

class FrakOutDataTableModel;
class FrakOutDrawType;
class FrakOutGraphicsView;
class FrakOutScene;
class QGraphicsItemGroup;
class QItemSelection;
class QModelIndex;
class QTableView;
class QUndoStack;

class FrakOutController : public QObject
{
    Q_OBJECT

public:
    FrakOutController(FrakOutGraphicsView *graphicsView, QTableView *tableView, QObject *parent = 0);
    ~FrakOutController();
    void addCell(const QPointF& sceneCoordinates);
    /**
      * Adds a sheet to the beginning or end of the table (depending on the sheet index).
      * Note that the cell dimension should be correct for the position being added to.
      */
    void addSheet(int sheetIndex, const FrakOutDataItem& sheet);
    const QString& currentFilename() const;
    void deleteSheet(int sheetIndex);
    void newFromFile(const QString& filename);
    int numSheets() const;
    bool openFrakOutFile(const QString& filename);
    void removeCell(const QPointF& sceneCoordinates);
    void removeCellsForSheet(int sheetIndex);
    bool saveFrakOutFile(const QString& filename);
    void setCellsForSheet(int sheetIndex, const QSet<QPair<int,int> >& cells);

    /**
      * Sets the current sheet index, selects the sheetIndex in the table and
      * then updates the scene with the sheet data.
      * @param sheetIndex An index identifying the sheet.
      */
    void setCurrentSheet(int sheetIndex);
    void setTool(const FrakOutDrawType* const drawType);
    void setZoomLevel(double zoom);
    QUndoStack* undoStack() const;
    double zoomLevel() const;

public slots:
    void slotAddItemBeginning();
    void slotAddItemEnd();
    void slotDeleteSheet();
    void slotClearCellsFromCurrentSheet();
    void slotGraphicsViewClick(const QPointF& sceneCoordinates);
    void slotZoomLevelChanged(double zoomInc);

signals:
    void signalCurrentSheetChanged(int sheetIndex);

private slots:
    void slotTableClicked(const QModelIndex& index);

private:
    void clearGroupFromScene(QGraphicsItemGroup *group);
    void initialiseScene();
    void populateSceneWithCells();
    void populateSceneWithGrid();
    QPair<int,int> sceneCoordinatesToCell(const QPointF& sceneCoordinates);

private:
    QGraphicsItemGroup *m_cellItemGroup;
    QString m_currentFilename;

    /** The index of the current fracalc item. */
    int m_currentIndex;
    const FrakOutDrawType* m_currentTool;
    FrakOutData m_fracalcData;
    FrakOutGraphicsView *m_graphicsView;
    QGraphicsItemGroup *m_gridGroup;
    FrakOutScene *m_scene;
    FrakOutDataTableModel *m_tableModel;
    QTableView *m_tableView;
    QUndoStack *m_undoStack;
    double m_zoom;
};

#endif // FRACALCCONTROLLER_H
